package com.yunqiao.api.controller;

import cn.hutool.core.lang.Console;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.XmlUtil;
import com.alipay.api.AlipayApiException;
import com.aliyuncs.exceptions.ClientException;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.gexin.fastjson.JSON;
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
import com.github.binarywang.wxpay.service.WxPayService;
import com.yunqiao.api.annotation.Login;
import com.yunqiao.api.annotation.LoginUser;
import com.yunqiao.common.exception.CustomApiException;
import com.yunqiao.common.utils.ApiResponse;
import com.yunqiao.common.utils.MapToolsUtils;
import com.yunqiao.common.utils.PageUtils;
import com.yunqiao.service.api.OrderCashService;
import com.yunqiao.service.api.OrderService;
import com.yunqiao.service.api.UserService;
import com.yunqiao.service.api.entity.OrderCashEntity;
import com.yunqiao.service.api.entity.OrderEntity;
import com.yunqiao.service.api.entity.UserEntity;
import com.yunqiao.service.api.vo.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.java.Log;
import org.aspectj.weaver.ast.Or;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;


/**
 * 订单信息
 *
 * @author Crocutax
 * @email wangxw725@163.com
 * @date 2019-03-03 21:58:45
 */
@RestController
@RequestMapping("api/order")
@Api(tags = "OrderApiController", description = "订单信息管理")
@Log
public class OrderApiController {

    @Autowired
    private OrderService orderService;
    @Autowired
    private OrderCashService orderCashService;
    @Autowired
    private WxPayService wxPayService;
    @Autowired
    private UserService userService;
    /**
     * 列表
     */
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "用户id", required = false, paramType = "query", dataType = "Long"),
            @ApiImplicitParam(name = "driverId", value = "司机id", required = false, paramType = "query", dataType = "Long"),
            @ApiImplicitParam(name = "statusTotal", value = "大方向订单状态:1 ：运输中 2：已完成 3：已取消", required = false, allowableValues = "100,200,300,400,500,1000", paramType = "query", dataType = "int"),
            @ApiImplicitParam(name = "status", value = "100待接单-200待取货-300运输中-400用户点击已送达-500：司机点击已送达 600已完成-700已评价- 1000已关闭", required = false, allowableValues = "100,200,300,400,500,1000", paramType = "query", dataType = "int"),
            @ApiImplicitParam(name = "address", value = "经纬度", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "page", value = "页码", required = false, defaultValue = "1", paramType = "query", dataType = "int"),
            @ApiImplicitParam(name = "limit", value = "数量", required = false, defaultValue = "10", paramType = "query", dataType = "int"),
    })
    @GetMapping("/list")
    @ApiOperation("查询订单信息 列表")
    public ApiResponse<PageUtils<OrdersVo>> list(@ApiIgnore @RequestParam Map<String, Object> params) {
        PageUtils page = orderService.queryPage(params);
        return new ApiResponse<>(page);
    }
    @Login
    @GetMapping("/v1/list")
    @ApiOperation("查询订单信息 列表 第二个版本")
    public ApiResponse<List<OrdersVo>> listv1(@ApiIgnore @RequestParam Map<String, Object> params,@LoginUser UserEntity user) {
        params.put("car_type_id",user.getCarTypeId());
        params.put("userId",user.getId());
        return new ApiResponse<>(orderService.queryPagev1(params));
    }
    /**
     * 信息
     */
    @GetMapping("/info/{id}")
    @ApiOperation("查询单个订单信息")
    public ApiResponse<OrdersVo> info(@PathVariable("id") Long id) {
        if (id == null) {
            throw new CustomApiException("ID不能为空");
        }
        OrdersVo order = orderService.getDetails(id);
        if(order.getDriverName()!=null){
            order.setDriverName(order.getDriverName().substring(0,1)+"师傅");
        }
        return new ApiResponse<>(order);
    }

    /**
     * 保存  用户下单(支付宝  微信   余额)
     */
    @PostMapping("/save")
    @ApiOperation("保存  用户下单(支付宝  微信   余额)")
    public ApiResponse save(@RequestBody OrderEntityVo order) throws Exception {
        UserEntity user=userService.getById(order.getUserId());
        return new ApiResponse<>(orderService.saveOrder(order,order.getPayType(),user.getWxCloudOpenid()));
    }

    /**
     * 代理商审核通过，付代理费下单
     */
    @PostMapping("/saveOrder")
    @ApiOperation("代理商社和通过，付代理费")
    public ApiResponse<String> PayingCommission(@RequestBody ApplyPartnerEntityVo applyPartnerEntity) throws Exception {
        String result = this.orderCashService.PayingCommission(applyPartnerEntity);
        return new ApiResponse<>(result);
    }

    /**
     * 支付宝成功回调
     *
     * @param request
     * @param response
     * @throws AlipayApiException
     */
    @PostMapping("/alipaySuccessCallBack")
    @ApiOperation("支付宝成功回调")
    public String alipaySuccessCallBack(HttpServletRequest request, HttpServletResponse response) throws Exception {
        Map<String, String> retMap = new HashMap<String, String>();

        Set<Map.Entry<String, String[]>> entrySet = request.getParameterMap().entrySet();

        for (Map.Entry<String, String[]> entry : entrySet) {
            String name = entry.getKey();
            String[] values = entry.getValue();
            int valLen = values.length;

            if (valLen == 1) {
                retMap.put(name, values[0]);
            } else if (valLen > 1) {
                StringBuilder sb = new StringBuilder();
                for (String val : values) {
                    sb.append(",").append(val);
                }
                retMap.put(name, sb.toString().substring(1));
            } else {
                retMap.put(name, "");
            }
        }
        Console.log(retMap);
        log.info(retMap.toString());
        log.info(retMap.get("out_trade_no"));
        return orderService.aliPaySuccess(retMap.get("out_trade_no"));
    }

    /**
     * 微信支付成功回调
     *
     * @param request
     * @param response
     * @return
     */
    @PostMapping("/wechatpaySuccessCallBack")
    @ApiOperation("微信成功回调")
    public String wechatpaySuccessCallBack(HttpServletRequest request, HttpServletResponse response) throws Exception {
        Console.log("微信支付回调===========================");
        Map<String, Object> params = null;
        InputStream inStream = null;
        ByteArrayOutputStream outSteam = null;
        try {
            inStream = request.getInputStream();
            outSteam = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = inStream.read(buffer)) != -1) {
                outSteam.write(buffer, 0, len);
            }
            String resultxml = new String(outSteam.toByteArray(), "utf-8");
            Console.log(resultxml);
            params = XmlUtil.xmlToMap(resultxml);

        } catch (IOException e) {
            throw new CustomApiException("支付回调异常");
        } finally {
            if (ObjectUtil.isNotNull(outSteam)) {
                outSteam.close();
            }
            if (ObjectUtil.isNotNull(inStream)) {
                inStream.close();
            }
        }

        // 结果正确
        String orderNumber = MapUtil.getStr(params, "out_trade_no");
        return orderService.aliPaySuccess(orderNumber);
    }


    /**
     * 微信退款成功回调  (不用回调了，直接在成功后写逻辑)
     *
     * @param request
     * @return
     */
    @PostMapping("/wechatrefundSuccessCallBack")
    @ApiOperation("微信退款成功回调")
    public String wechatrefundSuccessCallBack(HttpServletRequest request) throws Exception {
        Console.log("微信退款回调===========================");
        InputStream inStream = null;
        ByteArrayOutputStream outSteam = null;
        String orderNumber=null;
        try {
            inStream = request.getInputStream();
            outSteam = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = inStream.read(buffer)) != -1) {
                outSteam.write(buffer, 0, len);
            }
            String resultxml = new String(outSteam.toByteArray(), "utf-8");
            WxPayRefundNotifyResult result= wxPayService.parseRefundNotifyResult(resultxml);
            // 结果正确
            orderNumber = result.getReqInfo().getOutTradeNo();
        } catch (IOException e) {
            throw new CustomApiException("退款回调异常");
        } finally {
            if (ObjectUtil.isNotNull(outSteam)) {
                outSteam.close();
            }
            if (ObjectUtil.isNotNull(inStream)) {
                inStream.close();
            }
        }
        orderService.alirefundSuccess(orderNumber);
        return "success";
    }


    /**
     * 修改
     */
    @Login
    @PutMapping("/update/{id}")
    @ApiOperation("修改订单信息")
    public ApiResponse update(@PathVariable Long id, OrderEntity order) {
        OrderEntity dbItem = orderService.getById(id);
        if (dbItem == null) {
            throw new CustomApiException("ID有误, 未找到对应数据");
        }
        orderService.updateById(order);
        return new ApiResponse<>();
    }

    /**
     * 删除
     */
    @Login
    @DeleteMapping("/delete/{id}")
    @ApiOperation("删除订单信息")
    public ApiResponse delete(@PathVariable Long id) {
        if (id == null) {
            throw new CustomApiException("ID不能为空");
        }
        orderService.removeById(id);
        return new ApiResponse<>();
    }


    /**
     * 列表
     */
    @ApiImplicitParams({
            @ApiImplicitParam(name = "driverId", value = "司机id", required = true, paramType = "query", dataType = "long"),
            @ApiImplicitParam(name = "date", value = "时间", required = false, paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "page", value = "页码", required = false, defaultValue = "1", paramType = "query", dataType = "int"),
            @ApiImplicitParam(name = "limit", value = "数量", required = false, defaultValue = "10", paramType = "query", dataType = "int")
    })
    @GetMapping("/getList")
    @ApiOperation("查询订单统计")
    public ApiResponse<OrderVo<PageUtils<OrderEntity>>> getList(@ApiIgnore @RequestParam Map<String, Object> params) {
        OrderVo orderVo = new OrderVo();
        PageUtils<OrderEntity> page = orderService.queryPage(params);
        orderVo.setPage(page);
        orderVo.setTotal(page.getList().size());
        BigDecimal totalPrice = orderService.getTotalPrice(params);
        orderVo.setTotalPrice(totalPrice);
        return new ApiResponse<>(orderVo);
    }

    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "司机用户id", required = true, paramType = "query", dataType = "long"),
            @ApiImplicitParam(name = "orderId", value = "订单id", required = true, paramType = "query", dataType = "long")
    })
    @PostMapping("/robOrder")
    @ApiOperation("司机抢单")
    public ApiResponse<Object> robOrder(@RequestBody Map<String, Object> params) throws ClientException {
        this.orderService.robOrder(params);
        return new ApiResponse<>();
    }

    @PostMapping("/claimGoods/{orderId}")
    @ApiOperation("司机取货")
    public ApiResponse<Object> claimGoods(@PathVariable @ApiIgnore Long orderId) {
        this.orderService.claimGoods(orderId);
        return new ApiResponse<>();

    }
    @PostMapping("/userOrder/{id}")
    @ApiOperation("根基用户ID获取最新未完成订单")
    public ApiResponse<Object> queryOrderByUserId(@PathVariable @ApiIgnore Long id) {
        return new ApiResponse<>(this.orderService.queryOrderByUserId(id));

    }
    @GetMapping("/outTradeNo/{id}")
    @ApiOperation("根基用户订单编号获取最新未完成订单")
    public ApiResponse<Object> queryOrderByUserId(@PathVariable @ApiIgnore String id) {
        return new ApiResponse<>(this.orderService.getMap(new QueryWrapper<OrderEntity>().eq("order_number",id)));

    }
    @ApiImplicitParams({
            @ApiImplicitParam(name = "orderId", value = "订单id", required = true, paramType = "query", dataType = "long"),
            @ApiImplicitParam(name = "status", value = "400:用户完成 500 司机完成", required = true, paramType = "query", dataType = "int")
    })
    @PostMapping("/completeOrder")
    @ApiOperation("司机 用户 点击完成订单")
    public ApiResponse<Object> completeOrder(@RequestBody Map<String, Object> params) {
        this.orderService.completeOrder(MapUtil.getLong(params, "orderId"), MapUtil.getInt(params, "status"));
        return new ApiResponse<>();
    }

    @ApiImplicitParams({
            @ApiImplicitParam(name = "carType", value = "车类型", required = false, paramType = "query", dataType = "long"),
            @ApiImplicitParam(name = "startDetails", value = "发货详细地址", required = false, paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "endDetails", value = "发货详细地址", required = false, paramType = "query", dataType = "String")
    })
    @GetMapping("/getPrice")
    @ApiOperation("获取价格")
    public ApiResponse<Map<String, Object>> getPrice(@ApiIgnore @RequestParam Map<String, Object> params) {
        Map<String, Object> map = this.orderService.getPrice(params);
        return new ApiResponse<>(map);
    }

    @ApiImplicitParams({
            @ApiImplicitParam(name = "orderId", value = "订单id", required = true, paramType = "query", dataType = "long"),
            @ApiImplicitParam(name = "cancelReason", value = "取消原因", required = true, paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "cancelPeople", value = "1:司机取消，2：用户取消", required = true, paramType = "query", dataType = "int"),
            @ApiImplicitParam(name = "payType", value = "如果不空就是微信小程序退款", required = true, paramType = "query", dataType = "int")
    })
    @PostMapping("/cancelOrder")
    @ApiOperation("取消订单")
    public ApiResponse<BigDecimal> cancelOrder(@RequestBody Map<String, Object> params) throws Exception {
        orderService.cancelOrder(MapUtil.getLong(params, "orderId"), MapUtil.getStr(params, "cancelReason"), MapUtil.getInt(params, "cancelPeople"),MapUtil.getInt(params, "payType"));
        return new ApiResponse<>();
    }

    @ApiImplicitParam(name = "details", value = "详细地址", required = true, paramType = "query", dataType = "long")
    @GetMapping("/getLocation")
    @ApiOperation("获取经纬度")
    public ApiResponse<String> getLocation(String details,Integer orderId) {
        return new ApiResponse<>(MapToolsUtils.getLocation(details));
    }

    /**
     * 付押金  支付
     */
    @ApiImplicitParam(name = "userId", value = "用户id", required = false, paramType = "query", dataType = "String")
    @PostMapping("/cashPrice")
    @ApiOperation("alipay支付")
    public ApiResponse<String> cashPrice(@RequestBody Dict dict) throws Exception {
        return new ApiResponse<>(this.orderCashService.cashPrice(dict.getLong("userId"), dict.getInt("type")));
    }

    /**
     * 充值
     */
    @PostMapping("/reCharge")
    @ApiOperation("充值")
    public ApiResponse<String> reCharge(@RequestBody OrderCashEntityVo orderCashEntity) throws Exception {
        return new ApiResponse<>(this.orderCashService.reCharge(orderCashEntity,orderCashEntity.getPayType(),orderCashEntity.getWxOpenId()));
    }

    /**
     * 获取拒单率，和准点率
     */
    @GetMapping("/getFiducialPoint")
    @ApiOperation("获取拒单率，和准点率")
    public ApiResponse<Dict> getFiducialPoint(Long userId) {
        return new ApiResponse<>(this.orderCashService.getFiducialPoint(userId));
    }

    /**
     * 根据gps详细获取详细地址
     */
    @GetMapping("/getAddressOfLocation")
    @ApiOperation("根据用户位置获取详细的地址")
    public ApiResponse getAddress(String location) {
        return new ApiResponse(MapToolsUtils.getAddressFormatted(location));
    }
    @GetMapping("/distance")
    @ApiOperation("根据用户和司机的位置获取 距离")
    public ApiResponse getAddressDistance(String start,String end){
        return new ApiResponse(MapToolsUtils.getDistances(start, end));


    }
}
